//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

use crate::notice_decode::new_wrong_session_notice;
use proto_gen_rust::user_mail_api::user_mail_api_client::UserMailApiClient;
use proto_gen_rust::user_mail_api::*;
use tauri::{
    plugin::{Plugin, Result as PluginResult},
    AppHandle, Invoke, PageLoadPayload, Runtime, Window,
};

#[tauri::command]
async fn create_account<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: CreateAccountRequest,
) -> Result<CreateAccountResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserMailApiClient::new(chan.unwrap());
    match client.create_account(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == create_account_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("create_account".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn update_account<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: UpdateAccountRequest,
) -> Result<UpdateAccountResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserMailApiClient::new(chan.unwrap());
    match client.update_account(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_account_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("update_account".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn list_account<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: ListAccountRequest,
) -> Result<ListAccountResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserMailApiClient::new(chan.unwrap());
    match client.list_account(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_account_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("list_account".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn remove_account<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: RemoveAccountRequest,
) -> Result<RemoveAccountResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserMailApiClient::new(chan.unwrap());
    match client.remove_account(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == remove_account_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("remove_account".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn get_mail_status<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: GetMailStatusRequest,
) -> Result<GetMailStatusResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserMailApiClient::new(chan.unwrap());
    match client.get_mail_status(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == get_mail_status_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("get_mail_status".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn list_mail<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: ListMailRequest,
) -> Result<ListMailResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserMailApiClient::new(chan.unwrap());
    match client.list_mail(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_mail_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("list_mail".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}


#[tauri::command]
async fn get_mail_detail<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: GetMailDetailRequest,
) -> Result<GetMailDetailResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserMailApiClient::new(chan.unwrap());
    match client.get_mail_detail(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == get_mail_detail_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("get_mail_detail".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn remove_mail<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: RemoveMailRequest,
) -> Result<RemoveMailResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserMailApiClient::new(chan.unwrap());
    match client.remove_mail(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == remove_mail_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("remove_mail".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn set_mail_state<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: SetMailStateRequest,
) -> Result<SetMailStateResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserMailApiClient::new(chan.unwrap());
    match client.set_mail_state(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == set_mail_state_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("set_mail_state".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

pub struct UserMailApiPlugin<R: Runtime> {
    invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync + 'static>,
}

impl<R: Runtime> UserMailApiPlugin<R> {
    pub fn new() -> Self {
        Self {
            invoke_handler: Box::new(tauri::generate_handler![
                create_account,
                update_account,
                list_account,
                remove_account,
                get_mail_status,
                list_mail,
                get_mail_detail,
                remove_mail,
                set_mail_state,
            ]),
        }
    }
}

impl<R: Runtime> Plugin<R> for UserMailApiPlugin<R> {
    fn name(&self) -> &'static str {
        "user_mail_api"
    }
    fn initialization_script(&self) -> Option<String> {
        None
    }

    fn initialize(&mut self, _app: &AppHandle<R>, _config: serde_json::Value) -> PluginResult<()> {
        Ok(())
    }

    fn created(&mut self, _window: Window<R>) {}

    fn on_page_load(&mut self, _window: Window<R>, _payload: PageLoadPayload) {}

    fn extend_api(&mut self, message: Invoke<R>) {
        (self.invoke_handler)(message)
    }
}